package mobileann.mafamily.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import com.mofind.android.base.L;

import mobileann.mafamily.act.main.FS;
import mobileann.mafamily.model.TCPSocket;
import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;

/**
 * <p>收集项格式为：事件产生时间（yyyy-MM-dd HH:mm:ss）+ 事件（按编号来约定，详见下方定义） + 事件描述（见下方）
 * 
 * <p>主要收集事件：
 * <br> 1：网络断开（不需要事件描述）;
 * <br> 2：有网络（事件描述里填写网络类型）;
 * <br> 3：程序启动（不需要事件描述）;
 * <br> 4：程序崩溃（事件描述里填写崩溃时调用栈的相关信息）;
 * <br> 5：程序被意外中止（不需要事件描述）;
 * <br> 6：程序的内存占用（事件描述里填写当时程序占用的内存数，单位MB，每一小时收集）;
 * <br> 7：应用详情每次上传的数据（）;
 * <br> 8：应用详情每次从数据库中取数据（）;
 * <br> 9：应用详情每次存入数据（）;
 * <br> 10：定位rtc;
 * <br> 11：运动检测;
 *  
 * <p>上报数据：
 *  	以上定义事件明细项，上报数据时需要把当前收集到的明细项依条全部上报，
 *  	并且每次上报时需要额外附带上用户的跟屁虫账号（手机号），跟屁虫的版本
 *  	号，用户的手机型号，用户手机的android版本号。
 *  	(是否root，是否刷机？)
 * 		数据整理完毕后，需要统一做压缩，采用zlib。
 * 
 * <p>上报时间点：
 * <br>	1：程序每次启动后，如有未上报信息就上报;
 * <br>	2：手机每次检测到有网络连接后，如有未上报信息就上报；
 */
public class EventCollectingUtils {

	//	public static final int TAG_START = 1;
	//	public static final int TAG_NET = 2;

	private static EventCollectingUtils instance;

	private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
	private static final long INTERVAL = 7200000;
	//	private ClientEventModel model;
	private Context mContext;

	private EventCollectingUtils(Context mContext){
		this.mContext = mContext;
		//		model = new ClientEventModel(mContext);
	}

	public static synchronized EventCollectingUtils getInstance(Context c){
		if(instance == null){
			instance = new EventCollectingUtils(c);
		}
		return instance;
	}

	public void keepEvent(int tag, String addition){
		String time = getTime();
		String event = "";
		switch (tag) {
		case 2:
			event = time + "_" + tag + "_" +NetUtils.getInstance().getNetTypeDetails() + "\n";
			break;
		case 4:
			event = time + "_" + tag + "_" + addition + "\n";
			break;
		case 6:
			event = time + "_" + tag + "_" + MemUtils.getMemUse(mContext) + "\n";
			break;
		case 7:
			event = time + "_" + tag + "_" + addition  + "\n";
			break;
		case 8:
			event = time + "_" + tag + "_" + addition + "\n";
			break;
		case 9:
			event = time + "_" + tag + "_" + addition + "\n";
			break;
		case 11:
			event = time + "_" + tag + "_" + addition + "\n";
			break;
		default:
			event = time + "_" + tag + "\n";
			break;
		}
		if(!TextUtils.isEmpty(event)){
			//			model.insertEvent(event);
			saveEvent2File(event);
		}
	}

	public void keepEventNet(){
		if(NetUtils.getInstance().netstate() == 0){
			keepEvent(1, null);
		}else{
			keepEvent(2, null);
		}
	}

	private String getTime(){
		String time = formatter.format(new Date());
		return time;
	}

	//	public void sendEventInfo2Server(){
	//		String deviceInfo = collectDeviceInfo();
	//		String allInfo = getAllEvent();
	//		String info = allInfo + deviceInfo;
	//		byte[] data = ZLibUtils.compressStr(info);
	//		L.i("Event", info.getBytes().length + ":::" + data.length);
	//	}
	//	
	//	private void cleanData(){
	//		model.deleteClientEventTable();
	//	}
	//	
	//	private String getAllEvent(){
	//		List<String> allEvent = model.queryClientEventAll();
	//		StringBuilder sb = new StringBuilder();
	//		if(allEvent != null && allEvent.size() > 0){
	//			for(String s : allEvent){
	//				sb.append(s).append("#");
	//			}
	//			return sb.toString();
	//		}
	//		return "";
	//	}

	private String collectDeviceInfo(){
		String uid = SPUtils.getUID();//账号
		String version = PhoneInfoUtils.getVersion(mContext);//版本号
		String model = PhoneInfoUtils.getPhoneModel();//手机型号
		String release = PhoneInfoUtils.getRelease();//android版本号
		String isRoot = "root_"+isRoot();//是否root
		String DeviceInfo = uid+"#"+version+"#"+model+"#"+release+"#"+isRoot;
		//		L.i("DeviceInfo", DeviceInfo);
		return DeviceInfo;
	}

	private boolean isRoot(){
		boolean root = false;
		try {
			if ((!new File("/system/bin/su").exists())
					&& (!new File("/system/xbin/su").exists())) {
				root = false;
			} else {
				root = true;
			}
		} catch (Exception e) {
			L.e("maf", "error--", e);
		}
		return root;
	}

	private void saveEvent2File(String event) {
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			try {
				String dirName = getDirName();
				File dir = new File(dirName);
				if (!dir.exists())
					dir.mkdir();
				String textName = getSrcFileName();
				FileWriter writer = new FileWriter(textName, true);
				writer.write(event);
				writer.close();
			} catch (Exception e) {
				L.e("maf", "error--", e);
			}
		}
	}

	private void saveDeviceInfo2File(){
		String info = collectDeviceInfo();
		if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			try {
				String dirName = getDirName();
				File dir = new File(dirName);
				if (!dir.exists())
					dir.mkdir();
				String textName = getDirName() + File.separator + "DeviceInfo.txt";
				FileOutputStream fos = new FileOutputStream(textName);      
				fos.write(info.getBytes()); 
				fos.close();
			} catch (Exception e) {
				L.e("maf", "error--", e);
			}
		}
	}

	//===============================
	/**
	 *  根据路径删除指定的目录或文件，无论存在与否
	 *@param sPath  要删除的目录或文件
	 *@return 删除成功返回 true，否则返回 false。
	 */
	private boolean DeleteFolder(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 判断目录或文件是否存在
		if (!file.exists()) {  // 不存在返回 false
			return flag;
		} else {
			// 判断是否为文件
			if (file.isFile()) {  // 为文件时调用删除文件方法
				return deleteFile(sPath);
			} else {  // 为目录时调用删除目录方法
				return deleteDirectory(sPath);
			}
		}
	}

	/**
	 * 删除单个文件
	 * @param   sPath    被删除文件的文件名
	 * @return 单个文件删除成功返回true，否则返回false
	 */
	public boolean deleteFile(String sPath) {
		boolean flag = false;
		File file = new File(sPath);
		// 路径为文件且不为空则进行删除
		if (file.isFile() && file.exists()) {
			file.delete();
			flag = true;
		}
		return flag;
	}

	/**
	 * 删除目录（文件夹）以及目录下的文件
	 * @param   sPath 被删除目录的文件路径
	 * @return  目录删除成功返回true，否则返回false
	 */
	public boolean deleteDirectory(String sPath) {
		//如果sPath不以文件分隔符结尾，自动添加文件分隔符
		if (!sPath.endsWith(File.separator)) {
			sPath = sPath + File.separator;
		}
		File dirFile = new File(sPath);
		//如果dir对应的文件不存在，或者不是一个目录，则退出
		if (!dirFile.exists() || !dirFile.isDirectory()) {
			return false;
		}
		boolean flag = true;
		//删除文件夹下的所有文件(包括子目录)
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			//删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag) break;
			} //删除子目录
			else {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag) break;
			}
		}
		if (!flag) return false;
		//删除当前目录
		if (dirFile.delete()) {
			return true;
		} else {
			return false;
		}
	}

	private static String sourceFileName;

	private String getDirName(){
		sourceFileName = FS.getInstance().getParentPath() + File.separator + "event_log";
		return sourceFileName;
	}

	private String getSrcFileName(){
		String fileName = getDirName() + File.separator + getFileName() +".txt";
		return fileName;
	}

	private String getDstFileName(){
		String fileName = FS.getInstance().getParentPath() + File.separator + getFileName() + ".zip";
		return fileName;
	}

	public void setFileName(){
		DateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.getDefault());
		String name = formatter.format(new Date());
		SPUtils.setNewFileName(name);
	}

	public String getFileName(){
		if(TextUtils.isEmpty(SPUtils.getNewFileName())){
			setFileName();
		}
		return SPUtils.getNewFileName();
	}

	public boolean eventLogSend(){
		File dir = new File(getDirName());
		if(!dir.exists()){
			return true;
		}else{
			File[] files = new File[0];
			if(dir.isDirectory()){
				files = dir.listFiles();
			}
			if(files == null || files.length == 0){
				return true;
			}
			for(File file : files){
				if(!file.getName().equals(SPUtils.getNewFileName())){
					return false;
				}
			}
			return true;
		}
	}
	public void sendEventLog(){
		if(!SPUtils.getEventLogTimeSetted()){
			String time = formatter.format(new Date());
			SPUtils.setEventLogTime(time);
			SPUtils.setEventLogTimeSetted(true);
		}
		if(SPUtils.getEventLogTimeSetted()){
			String oldTime = SPUtils.getEventLogTime();
			try {
				long old = formatter.parse(oldTime).getTime();
				long now = System.currentTimeMillis();
				long interval = now - old;
				if(interval > INTERVAL && NetUtils.getInstance().netstate() != 0 
						&& !eventLogSend()){
					BMapOfflineUtil.offlineMapCheck();
					String newTime = formatter.format(new Date());
					SPUtils.setEventLogTime(newTime);
					try {
						saveDeviceInfo2File();
						ZLibUtils.zipCompressByPath(getDirName(), getDstFileName());
						byte[] data = ZLibUtils.getBytesByPath(getDstFileName());
						TCPSocket.getInstance().send_eventlog(data);
					} catch (Exception e) {
						L.e("maf", "error--", e);
					}
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
	}

	public void deleteAllLog(){
		DeleteFolder(getDirName());
		DeleteFolder(getDstFileName());
	}

	public void deleteZip(){
		DeleteFolder(getDstFileName());
	}

	//	private void offlineMapCheck(){
	//		int count = SPUtils.getOfflineMapCheck() + 1;
	//		if(count == 3){
	//			SPUtils.setOfflineMapCheck(0);
	//			BMapOfflineUtil.getOfflineMap(null);
	//			BMapOfflineUtil.autoUpdate();
	//		}else{
	//			SPUtils.setOfflineMapCheck(count);
	//		}
	//	}
}
